package com.LachesismStorm.lachesism.websocket;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.LachesismStorm.lachesism.core.util.LachesismTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket服务端，用于处理视频聊天信令
 */
@Slf4j
@ServerEndpoint(value = "/video")
@Component
public class videoService {

    // 用于保存WebSocket连接对象
    public static ConcurrentHashMap<Integer, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 连接建立成功时调用
     */
    @OnOpen
    public void onOpen(Session session) {
        log.info("新的客户端连接: " + session.getId());
        Map<String, Object> userProperties = session.getUserProperties();
        int size = sessionMap.size();
        userProperties.put("index", size);
        sessionMap.put(size, session);
        sendMessage("ok", session);
    }

    /**
     * 连接关闭时调用
     */
    @OnClose
    public void onClose(Session session) throws IOException {
        Map<String, Object> userProperties = session.getUserProperties();
        Integer index = (Integer) userProperties.get("index");
        sessionMap.remove(index);
        String nickName = (String) userProperties.get("nickName");
        notification("用户：" + nickName + " 离开了");
    }

    /**
     * 接收消息，解析信令并转发给其他客户端
     */
    @OnMessage
    public void onMessage(String message, Session session) throws Exception {
        JSONObject json = JSONUtil.parseObj(message);
        String type = json.getStr("type");

        switch (type) {
            case "offer":
                broadcastOffer(json.getJSONObject("offer"), session);
                break;
            case "answer":
                broadcastAnswer(json.getJSONObject("answer"), session);
                break;
            case "iceCandidate":
                broadcastIceCandidate(json.getJSONObject("candidate"), session);
                break;
            default:
                // 处理其他类型的消息
                break;
        }
    }

    private void broadcastOffer(JSONObject offer, Session session) {
        // 广播offer给所有连接的用户，除了发送消息的用户
        sessionMap.forEach((key, peerSession) -> {
            if (peerSession != session) {
                peerSession.getAsyncRemote().sendText(JSONUtil.toJsonStr(new JSONObject().put("type", "offer").put("offer", offer)));
            }
        });
    }

    private void broadcastAnswer(JSONObject answer, Session session) {
        // 广播answer给所有连接的用户，除了发送消息的用户
        sessionMap.forEach((key, peerSession) -> {
            if (peerSession != session) {
                peerSession.getAsyncRemote().sendText(JSONUtil.toJsonStr(new JSONObject().put("type", "answer").put("answer", answer)));
            }
        });
    }

    private void broadcastIceCandidate(JSONObject candidate, Session session) {
        // 广播ICE候选到所有连接的用户，除了发送消息的用户
        sessionMap.forEach((key, peerSession) -> {
            if (peerSession != session) {
                peerSession.getAsyncRemote().sendText(JSONUtil.toJsonStr(new JSONObject().put("type", "iceCandidate").put("candidate", candidate)));
            }
        });
    }


    /**
     * 广播通知给所有用户
     */
    private static void notification(String message) {
        for (Session session : sessionMap.values()) {
            session.getAsyncRemote().sendText("/:notification/" + message);
        }
    }

    /**
     * 发送消息给客户端
     */
    private void sendMessage(String message, Session session) {
        session.getAsyncRemote().sendText(message);
    }

    /**
     * 处理错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket错误", error);
    }
}
